package good_src.Implementation;

import java.util.Collection;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;

import good_src.Interfaces.Afficheur;
import good_src.Interfaces.Algorithme;
import good_src.Interfaces.Capteur;
import good_src.Interfaces.MethodRequest;
import good_src.Interfaces.ObservateurCapteur;
import good_src.Interfaces.Subject;

/**
 * 
 * @author Tangi Midy & Fabien Le Peih
 * <p>Canal is the proxy of the AO pattern.</p>
 * <p>It sets the method requests and get the values of the futures</p>
 * permits the displayers update
 */
public class Canal extends Observable implements Capteur, ObservateurCapteur {

	private Subject<Integer> capteur;
	private ExecutorService scheduler;
	private Afficheur afficheur;
	private boolean isUpdatable = true;
	private long frequence;

	

	/**
	 * 
	 * @param capteur
	 *            the referenced capteur
	 */
	public Canal(Subject<Integer> capteur) {
		this.capteur = capteur;
		afficheur = new ConcreteAfficheur(this); // The referenced displayer
	}

	/**
	 * 
	 * @see good_src.Interfaces.Capteur#update()
	 */
	@Override
	public void update() {
		isUpdatable=false;// boolean for the versionned strategy (no impact on the other ones)
		frequence = (long) (100 * Math.random() * 10); // We admit the response frequency is random
		try {
			Thread.sleep(frequence);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		MethodRequest mr = new ConcreteMethodUpdate(this);
		scheduler.submit(mr);
		isUpdatable=true;
	}

	/**
	 * 
	 * @see good_src.Interfaces.Subject#getValue()
	 */
	@Override
	public Object getValue() {

		MethodRequest mr = new ConcreteMethodRequestGet();
		((ConcreteMethodRequestGet) mr).setCapteur(this.capteur);

		//This future will return the current value of the capteur
		Future future = scheduler.submit(mr);

		try {
			return future.get();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * @return the frequence
	 */
	public long getFrequence() {
		return frequence;
	}

	/**
	 * 
	 * @return the associated afficheur
	 */
	public Afficheur getAfficheur() {
		return afficheur;
	}

	/**
	 * Sets the displayer's name
	 * @param string the displayer's name
	 */
	public void setName(String string) {
		this.afficheur.setName(string);
	}

	/**
	 * 
	 * @param scheduler the associated scheduler
	 */
	public void setScheduler(ScheduledExecutorService scheduler) {
		this.scheduler = scheduler;
	}

	/**
	 * 
	 * @param subject the associated subject
	 */
	public void setSubject(Subject subject) {
		this.capteur = subject;
	}

	/**
	 * 
	 * @see good_src.Interfaces.Subject#getVersion()
	 */
	@Override
	public int getVersion() {
		return capteur.getVersion();
	}

	/**
	 * 
	 * @see good_src.Interfaces.ObservateurCapteur#isUpdatable()
	 */
	public boolean isUpdatable() {
		return isUpdatable;
	}

	/*********************************************** UNUSED METHODS ************************************************************/

	/**
	 * 
	 */
	@Override
	public boolean isTicking() {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * 
	 * @see good_src.Interfaces.Capteur#setTick(boolean)
	 */
	@Override
	public void setTick(boolean b) {
		// TODO Auto-generated method stub

	}

	/**
	 * 
	 * @see good_src.Interfaces.Subject#attach(java.util.Observer)
	 */
	@Override
	public void attach(Observer observer) {
		// TODO Auto-generated method stub

	}

	/**
	 * 
	 * @see good_src.Interfaces.Subject#detach(java.util.Observer)
	 */
	@Override
	public void detach(Observer observer) {
		// TODO Auto-generated method stub

	}

	/**
	 * 
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
	 */
	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub

	}

	/**
	 * 
	 * @see good_src.Interfaces.Capteur#getObservers()
	 */
	@Override
	public Collection getObservers() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 
	 * @see good_src.Interfaces.Subject#tick()
	 */
	@Override
	public void tick() {
		// TODO Auto-generated method stub

	}

	/**
	 * 
	 * @see good_src.Interfaces.Subject#getStrategy()
	 */
	@Override
	public Algorithme getStrategy() {
		// TODO Auto-generated method stub
		return null;
	}

	/** 
	 * @see good_src.Interfaces.Subject#setStrategy(Interfaces.Algorithme)
	 */
	@Override
	public void setStrategy(Algorithme algo) {
		// TODO Auto-generated method stub
		
	}

	/** 
	 * @see good_src.Interfaces.Subject#setCanaux(int)
	 */
	@Override
	public void setCanaux(int displayers) {
		// TODO Auto-generated method stub
		
	}

}
